package com.lxp.lambda;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @Author swd
 * @Create 2020/12/2 0002 10:16
 */
public class StreamApi {
    /**
     * Java 8中的Stream是对集合(collection)对象功能的增强，它专注于最集合对象进行各种非常便利、高效的
     *      聚合操作(aggregate operation)，或者大批量数据操作。
     *  Stream不是集合元素，它不是数据结果并不保存数据，只是有关算法和计算。
     *      就如同一个迭代器(iterator)，单向不可往复，数据只能遍历一次。
     *  数据源本身是可以无限的
     */

    /**
     * 流的使用详解：对Stream的使用就是实现一个filter-map-reduce过程，产生一个最终结果，或者导致一个副作用(side effect)。
     * 基本数据类型对应三种包装类型Stream：IntStream、LongStream、DoubleStream
     */

    /*
     * 典型用法：
     *  分为两种操作类型：Intermediate：一个流可以后面跟随零个或多个 intermediate 操作。
     *                   Terminal：一个流只能有一个terminal操作，当这个操作执行后，流就被使用“光”了，无法再被操作。
     *  intermediate操作:map (mapToInt, flatMap 等)、 filter、 distinct、 sorted、 peek、
     *                  limit、 skip、 parallel、 sequential、 unordered
     *  terminal操作：forEach、 forEachOrdered、 toArray、 reduce、 collect、 min、 max、
     *                count、 anyMatch、 allMatch、 noneMatch、 findFirst、 findAny、 iterator
     */
    public static void main(String[] args) {
        // mapOrflatMap();
        // filter();
        reduce();

    }

    private static void reduce() {
        // reduce主要作用是把 Stream 元素组合起来
        // 字符串连接，concat = "ABCD"
        String concat = Stream.of("A", "B", "C", "D").reduce("", String::concat);
        // 过滤，字符串连接，concat = "ace"
        concat = Stream.of("a", "B", "c", "D", "e", "F")
                .filter(x -> x.compareTo("Z") > 0)
                .reduce("", String::concat);
        // 求最小值，minValue = -3.0
        double minValue = Stream.of(-1.5, 1.0, -3.0, -2.0).reduce(Double.MAX_VALUE, Double::min);
        // 求和，sumValue = 10, 有起始值
        int sumValue = Stream.of(1, 2, 3, 4).reduce(0, Integer::sum);
        // 求和，sumValue = 10, 无起始值
        sumValue = Stream.of(1, 2, 3, 4).reduce(Integer::sum).get();
    }

    private static void filter() {
        // filter对原始的Stream进行某项测试，通过测试的元素被留下生成新Stream
        Integer[] nums = {1, 2, 3, 4, 5, 6};
        Integer[] array = Stream.of(nums).filter(n -> n % 2 == 0).toArray(Integer[]::new);
        System.out.println(Arrays.asList(array));
    }

    private static void mapOrflatMap() {
        //map生成1:1映射关系
        List<Integer> nums = Arrays.asList(1, 2, 3, 4);
        List<Integer> list = nums.stream().map(n -> n * n).collect(Collectors.toList());
        System.out.println(list);

        //flatMap一对多映射关系
        Stream<List<Integer>> inputStream = Stream.of(
                Arrays.asList(1),
                Arrays.asList(2, 3),
                Arrays.asList(4, 5, 6)
        );
        Stream<Integer> outputStream = inputStream.flatMap((childList) -> childList.stream());
    }


}
